package com.maxlen.camunda.service.impl;

import com.alibaba.nacos.shaded.org.checkerframework.checker.nullness.Opt;
import com.maxlen.camunda.constant.CamundaConstant;
import com.maxlen.camunda.entity.BpmnEntity;
import com.maxlen.camunda.entity.dto.CountByBpmnIdDTO;
import com.maxlen.camunda.entity.dto.InsertBpmnDTO;
import com.maxlen.camunda.entity.dto.UpdateBpmnDTO;
import com.maxlen.camunda.entity.vo.BpmnInfoVO;
import com.maxlen.camunda.entity.vo.BpmnListVO;
import com.maxlen.camunda.exception.CamundaException;
import com.maxlen.camunda.mapper.BpmnMapper;
import com.maxlen.camunda.service.BpmnService;
import com.maxlen.camunda.service.CamundaService;
import com.maxlen.camunda.utils.FileUtils;
import com.tcloudit.common.core.web.domain.AjaxResult;
import com.tcloudit.common.core.web.domain.PageEntity;
import com.tcloudit.common.core.web.page.TableDataInfo;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.repository.Deployment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

@Service
public class BpmnServiceImpl implements BpmnService {

    @Autowired
    private BpmnMapper bpmnMapper;

    @Autowired
    private CamundaService camundaService;

    /**
     * 添加流程模型
     * @param insertBpmnDTO 参数
     * @return 结果
     */
    @Override
    public int insertProcessBpmn(InsertBpmnDTO insertBpmnDTO) {
        String bpmnId = insertBpmnDTO.getBpmnId();
        if (CamundaConstant.NOT_UNIQUE.equals(checkBpmnIdUnique(bpmnId))) {
            throw new CamundaException("模型标识已存在");
        }
        BpmnEntity bpmnEntity = new BpmnEntity(insertBpmnDTO.getName(), bpmnId, insertBpmnDTO.getSort());
        bpmnEntity.setBytes(
                CamundaConstant.DEFAULT_BPMN
                        .replace(CamundaConstant.REPLACE_Id, bpmnId)
                        .replace(CamundaConstant.REPLACE_NAME, insertBpmnDTO.getName()).getBytes()
        );
        return bpmnMapper.add(bpmnEntity);
    }

    /**
     * 检查模型ID是否唯一
     * @param bpmnId 模型标识
     * @return 结果
     */
    @Override
    public String checkBpmnIdUnique(String bpmnId) {
        long count = bpmnMapper.checkBpmnIdUnique(bpmnId);
        if(count > 0){
            return CamundaConstant.NOT_UNIQUE;
        }
        return CamundaConstant.UNIQUE;
    }

    /**
     * 根据id获取模型文件
     * @param bpmnId 模型标识
     * @return 结果
     */
    @Override
    public String getBpmnFile(String bpmnId) throws Throwable {
        BpmnEntity bpmnEntity = bpmnMapper.getBpmnFile(bpmnId);
        Optional.ofNullable(bpmnEntity).orElseThrow((Supplier<Throwable>) () -> new CamundaException("数据为空"));
        return new String(bpmnEntity.getBytes());
    }

    /**
     * 根据 id 保存修改模型文件
     * @param file xml文件
     * @param bpmnId 模型标识
     */
    @Override
    public void saveBpmn(MultipartFile file, String bpmnId) {
        try (InputStream inputStream = file.getInputStream()) {
            byte[] bytes = FileUtils.readInputStream(inputStream).getBytes();
            bpmnMapper.saveBpmn(bpmnId, bytes);
        }catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改流程模型
     * @param updateBpmnDTO 参数
     * @return 结果
     */
    @Override
    public int updateProcessBpmn(UpdateBpmnDTO updateBpmnDTO) {
        return bpmnMapper.edit(updateBpmnDTO);
    }

    /**
     * 删除流程模型
     * @param ids 模型ID集合
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteProcessBpmn(String[] ids) {
        if(ids.length > 0){
            camundaService.removeProcessDefinition(ids);
            return bpmnMapper.remove(ids);

        }
        return 0;
    }

    /**
     * 获取流程模型列表
     * @param page 分页搜索参数
     * @return 结果
     */
    @Override
    public TableDataInfo selectProcessBpmn(PageEntity<String> page) {
        Integer count = bpmnMapper.getCount(page);
        List<BpmnListVO> BpmnEntityList = bpmnMapper.getList(page);
        return new TableDataInfo(BpmnEntityList, count);
    }

    /**
     * 获取流程模型详情
     * @param id 流程模型ID
     * @return 结果
     */
    @Override
    public BpmnInfoVO selectProcessBpmnInfo(String id) {
        return bpmnMapper.selectProcessBpmnInfo(id);
    }

}
